"""

.. module:: admintask
.. moduleauthor:: @author:  Edward Huynh

The purpose of this module is handle administration operations in the Reference Implementation.
   
.. seealso:: modules :mod:`<module>`

*Constants*:
.. data:: constant_1
        
    constant_1 is used for ......
        
.. data:: constant_2
        
    constant_2 is used for ......
"""

from datastore.resource import Resource
from runtime.task import Task
import datetime
import logging

class AdminTask(Task):
    """This class is a daemon task. It processes requests from admin operations.

    *Usage examples*::

        example code

    *Common Arguments for Class methods*:
        <arguments>
    
    *Audience*:
        <audience>
    
    *Constants*:
        .. data:: constant_1
        
            constant_1 is used for ......
        
        .. data:: constant_2
        
            constant_2 is used for ......
    """
    
    SPEAR_INTEGRATION_CONFIGURATION_PARAM_SPEAR_ADAPTOR_URL = 'spear_adaptor_url'
    SPEAR_INTEGRATION_CONFIGURATION_PARAM_SPEAR_ADAPTOR_USER_NAME = 'spear_adaptor_user_name'
    SPEAR_INTEGRATION_CONFIGURATION_PARAM_SPEAR_ADAPTOR_PASSWORD = 'spear_adaptor_password'
    SPEAR_INTEGRATION_CONFIGURATION_PARAM_SPEAR_ADAPTOR_APPLICATION_LIST_URL = 'spear_adaptor_application_list_url'
    SPEAR_INTEGRATION_CONFIGURATION_PARAM_SPEAR_ADAPTOR_APPLICATION_URL = 'spear_adaptor_application_url'
    SPEAR_INTEGRATION_CONFIGURATION_PARAM_SPEAR_ADAPTOR_ADMINISTRATOR_MENU_URL = 'spear_adaptor_administrator_menu_url'
    SPEAR_INTEGRATION_CONFIGURATION_PARAM_SPEAR_ADAPTOR_REFERRAL_URL = 'spear_adaptor_referral_url'
    SPEAR_INTEGRATION_CONFIGURATION_PARAM_SPEAR_ADAPTOR_APPLICATION_URL = 'spear_application_url'
    SPEAR_INTEGRATION_CONFIGURATION_PARAM_SPEAR_ADAPTOR_LOGIN_URL = 'spear_login_url'
    SPEAR_INTEGRATION_CONFIGURATION_PARAM_SPEAR_ADAPTOR_SHARED_SECRET = 'shared_secret'
    SPEAR_INTEGRATION_CONFIGURATION_PARAM_SPEAR_ADAPTOR_CURRENCY_OF_DATA = 'currency_of_data'
    SPEAR_INTEGRATION_CONFIGURATION_PARAMS = [(SPEAR_INTEGRATION_CONFIGURATION_PARAM_SPEAR_ADAPTOR_URL, 'http://10.100.1.1:8001/eDAIS'),
                                              (SPEAR_INTEGRATION_CONFIGURATION_PARAM_SPEAR_ADAPTOR_USER_NAME, ''),
                                              (SPEAR_INTEGRATION_CONFIGURATION_PARAM_SPEAR_ADAPTOR_PASSWORD, ''),
                                              (SPEAR_INTEGRATION_CONFIGURATION_PARAM_SPEAR_ADAPTOR_APPLICATION_LIST_URL, 'http://10.100.1.1:8001/SPEAR/Applist'),
                                              (SPEAR_INTEGRATION_CONFIGURATION_PARAM_SPEAR_ADAPTOR_APPLICATION_URL, 'http://10.100.1.1:8001/SPEAR/$srn/View'),
                                              (SPEAR_INTEGRATION_CONFIGURATION_PARAM_SPEAR_ADAPTOR_ADMINISTRATOR_MENU_URL, 'http://10.100.1.1:8001/SPEAR/Admin'),
                                              (SPEAR_INTEGRATION_CONFIGURATION_PARAM_SPEAR_ADAPTOR_REFERRAL_URL, 'http://10.100.1.1:8001/SPEAR/$srn/Referral'),
                                              (SPEAR_INTEGRATION_CONFIGURATION_PARAM_SPEAR_ADAPTOR_APPLICATION_URL, 'http://www.landexchange.vic.gov.au/spear/viewApplication.do?spearNum=$srn'),
                                              (SPEAR_INTEGRATION_CONFIGURATION_PARAM_SPEAR_ADAPTOR_LOGIN_URL, 'http://www.landexchange.vic.gov.au/spear/login/login.do'),
                                              (SPEAR_INTEGRATION_CONFIGURATION_PARAM_SPEAR_ADAPTOR_SHARED_SECRET, ''),
                                              (SPEAR_INTEGRATION_CONFIGURATION_PARAM_SPEAR_ADAPTOR_CURRENCY_OF_DATA, 300)
                                              ]
    
    def cb_start(self, method, uri, new_uri, result, context, **kwargs):
        """This function is called when the task starts. 
        
        :param method: <class> or <type>
        :param uri: The task Uri.
        :param new_uri: <class> or <type>
        :param result: <class> or <type>
        :param context: <class> or <type>
        :param kwargs: <class> or <type>
        """
        
        self.logger.log(logging.DEBUG, "***************** uri (%s), new_uri (%s)" % (uri, new_uri))
        
        # Make sure we look for ALL Uris that are children of our task Uri.
        # (i.e. make a collection of our Uri. 
        #
        # All 'put' messages to this task are interpreted as requests for Spaces Resources.
        #
        self.spaces_context.process(uri.admin.menu, get='cb_generate_admin_menu_view')
        self.spaces_context.process(uri.add('edais-connectivity-test'), put='cb_perform_edais_connectivity_test')
        self.spaces_context.process(uri.add('spear-integration-configuration'), put='cb_save_spear_integration_configuration', get='cb_get_spear_integration_configuration')

    def cb_generate_admin_menu_view(self, method, uri, return_value, result, context, **kwargs):
        """This method handles the GET request for the admin menu.
        
        :param method: <class> or <type>
        :param uri: The task Uri.
        :param return_value: Resource
        :param result: <class> or <type>
        :param context: <class> or <type>
        :param kwargs: <class> or <type>
        """
        
        spear_integration_configuration_resource = self.get_spear_integration_configuration_resource()
        rs = Resource()
        rs.set_var(AdminTask.SPEAR_INTEGRATION_CONFIGURATION_PARAM_SPEAR_ADAPTOR_ADMINISTRATOR_MENU_URL,
                   spear_integration_configuration_resource.get_var(AdminTask.SPEAR_INTEGRATION_CONFIGURATION_PARAM_SPEAR_ADAPTOR_ADMINISTRATOR_MENU_URL))
        rs.set_var(Resource.KEY_URI_SERVICES_TYPE_HTTP_SITE_ACTION_RESULT, 'admin-menu')        
        return (True, rs)
                
    def cb_get_spear_integration_configuration(self, method, uri, return_value, result, context, **kwargs):
        """This method handles the GET request for the spear integration configuration view.
        
        :param method: <class> or <type>
        :param uri: The task Uri.
        :param return_value: Resource
        :param result: <class> or <type>
        :param context: <class> or <type>
        :param kwargs: <class> or <type>
        """        
        spear_integration_configuration_resource = self.get_spear_integration_configuration_resource()
        return (True, spear_integration_configuration_resource)
                
    def cb_save_spear_integration_configuration(self, method, uri, return_value, result, context, **kwargs):
        """This method handles the POST request for the spear integration configuration view. This saves all the changes to the spear integration configuration parameters.
        
        :param method: <class> or <type>
        :param uri: The task Uri.
        :param return_value: Resource
        :param result: <class> or <type>
        :param context: <class> or <type>
        :param kwargs: <class> or <type>
        """          
        spear_integration_configuration_resource = self.get_spear_integration_configuration_resource()
        post_data = return_value.get_var(Resource.KEY_URI_SERVICES_TYPE_HTTP_REQUEST_DATA)
        # go through all the spear integration configuration parameters
        for (spear_integration_configuration_param_name, spear_integration_configuration_param_default_value) in AdminTask.SPEAR_INTEGRATION_CONFIGURATION_PARAMS:
            if spear_integration_configuration_param_name in post_data:
                spear_integration_configuration_resource.set_var(spear_integration_configuration_param_name, post_data[spear_integration_configuration_param_name])
            # what happens here? If there is not data posted should we resort to default values? No validation rules currently to define this.
            else:
                spear_integration_configuration_resource.set_var(spear_integration_configuration_param_name, spear_integration_configuration_param_default_value)
        uri_task = context.uri('task:')
        configuration_uri = uri_task.eplanning.reference.admintask.add('spear-integration-configuration')
        self.ds.put([spear_integration_configuration_resource])
        return (True, configuration_uri)
    
    def cb_perform_edais_connectivity_test(self, method, uri, return_value, result, context, **kwargs):
        """This method handles the POST request for the eDAIS connectivity test.
        
        :param method: <class> or <type>
        :param uri: The task Uri.
        :param return_value: Resource
        :param result: <class> or <type>
        :param context: <class> or <type>
        :param kwargs: <class> or <type>
        """

        # get the current time
        now = datetime.datetime.now()
        datetimestr =  now.strftime("%Y%m%dT%H%M%S")
                
        # TODO: code to send msg to SPEAR Adaptor
                
        # create dummy response for now
        rs = Resource()
        rs.message = "Connection successful {0}".format(datetimestr)
        id = context.uuid()
        result_uri = uri.add(id)
        context.put(result_uri, rs)
        return (True, result_uri)
        
    def get_spear_integration_configuration_resource(self):
        """This method retrieves the spear integration configuration resource from the datastore.
        """          
        ress = self.ds.find([(Resource.KEY_URI_PACKAGE_MODULENAME, 'reference.spear-integration-configuration')])
        # make sure there is only one resource returned
        if ress and len(ress) != 1:
            raise Exception('More than one SPEAR Integration Configuration resource found. Ids are {0}'.format([res.get_id() for res in ress]))
        spear_integration_configuration_resource = ress[0]
        return spear_integration_configuration_resource